package clasificador.redneuronal.neurona;

import java.util.Arrays;

import utils.Logger;

public class NeuronaSigmoide extends Neurona {

    double[] weights;

    @Override
    public double errorFunction(double[] errors) {
        //Logger.info("Calculando error para SIGMOIDE a partir de errores: " + Arrays.toString(errors));
        double error = 0.0;

        for (int i = 0; i < errors.length; i++) {
            error += errors[i];
        }

        //Logger.info("Error resultante: " + error);
        return error;
    }

    @Override
    public double activationFunction(double[] inputs) {
        double sum = weights[0];
        for (int i = 0; i < inputs.length; i++) {
            sum += weights[i + 1] * inputs[i];
        }
        //Logger.info("Suma de pesos: " + sum);
        return 1.0 / (1.0 + Math.exp(-sum));
    }

    @Override
    public double derivative(int i, double[] inputs, double output) {
        return output * (1 - output) * weights[i + 1];
    }

    @Override
    public void train(double learningCoefficient) {
        //Logger.info("***NEURONA SIGMOIDE***");
        //Logger.info("Pesos antes de la actualizacion: " + Arrays.toString(weights));
        double output = this.outputSignal.getValue();
        //Logger.info("Output: " + output);
        double error = this.errorSignal.getValue();
        //Logger.info("Error: " + error);
        //Logger.info("lcoef: " + learningCoefficient);
        //Logger.info("lcoef * output*(1-output)*error: " + (learningCoefficient * output*(1-output)*error));

        /* Esto para el multicapa, cuando no hay que contar ya la verosimilitud */
        this.weights[0] -= learningCoefficient * output * (1 - output) * error;
        for (int i = 0; i < this.weights.length - 1; i++) {
            this.weights[i + 1] -= learningCoefficient * output * (1 - output) * error * this.getInputValue(i);
        }
        /* Esto cuando es la ultima capa, ya que hay que tener en cuenta la verosimilitud */
        /*this.weights[0] -= learningCoefficient * error;
         for( int i = 0; i < this.weights.length - 1; i++ ) {
         this.weights[i + 1] -= learningCoefficient * error * this.getInputValue(i);
         }*/

        //Logger.info("Pesos tras la actualizacion: " + Arrays.toString(weights));
        //Logger.info("***FIN NEURONA SIGMOIDE***");
    }

    @Override
    public void init() {
        this.weights = new double[this.getNInputs() + 1];

        weights[0] = 0.0;

        for (int i = 1; i <= this.getNInputs(); i++) {
            weights[i] = 0.001 * (2 * Math.random() - 1);
        }

    }
}
